﻿using UnityEngine;
using System.Collections.Generic;
using TTGame;
using System.Collections;

/*
 * FSM
 * FSM基础类（使用协程）
 *
 * 使用协程，合并OnEnter\Update\OnExit逻辑到一个协程方法，
 *      1、三个方法之间的逻辑联系，从底层放到前面来，逻辑更连贯清晰。
 *         不用再考虑底层是在什么时机回调Update\Exit。也不用强行把代码拆散在两个方法里。
 *      2、顺便减少了底层切换状态的逻辑复杂度
 *
 * 希望可以完全剥离FSM，不再写FSM逻辑
 * 对象注册相应FSMState方法，不再需要考虑状态机的跳转逻辑。。
 *
 * 依赖：
 * 不依赖于其他类
 *
 * ！不写重复代码！
 * @author TTun
 * @date 7/12/2017 5:16:56 PM
 */
namespace TTGameEngine {

public delegate void FSMState_updateFunc(float dt);
public delegate bool FSMState_onEnterFunc();
public delegate bool FSMState_onExitFunc();

public interface IFSMState {
    //定义接口属性
    string Name { get; set; }
    int StateID { get; set; }
    //一切换就会调用，免得还没update就被后面的状态切换顶替掉。
    void OnEnter();
    IEnumerator updateState();
    bool IsCanChangeState(int state);
}

public class FSMSystem : MonoBehaviour {

    Dictionary<int, IFSMState> m_states = new Dictionary<int, IFSMState>();//状态表id FsmState
    IFSMState m_curState;//当前状态
    bool m_isPause = false; // 暂停 不再接受状态
    bool isFSMRunning = false;

    int preStateID = -1;

    Puppet debug_obj;
    void Awake() {
        debug_obj = GetComponent<Puppet>();
    }

    //[Debug]防止状态还没update，就被后面的状态顶替掉了。
    bool debug_isStateChanged = false;
    public int CurrentState {
        get {
             Animator anim2;
             Animation anim3;
            if(m_curState == null) {
                return -1;
            }
            return m_curState.StateID;
        } set {
            if(debug_isStateChanged) {
                debug_obj.PuppetLogWarning("状态没有update[{0}].newState:[{1}]",
                                           m_curState != null ? ((PuppetStateID)m_curState.StateID).ToString() : "Null State",
                                           ((PuppetStateID)value).ToString());
            }
            int stateID = value;
            IFSMState newState = null;
            m_states.TryGetValue(stateID, out newState);
            if(newState != null) {
                preStateID = CurrentState;
                m_curState = newState;
                debug_isStateChanged = true;
                //防止状态还没update，就被后面的状态顶替掉了。
                m_curState.OnEnter();
            } else {
                debug_obj.PuppetLogError("No Found State:[{0}]", ((PuppetStateID)stateID).ToString());
            }
        }
    }

    public IFSMState GetFSMState(int stateID) {
        IFSMState state = null;
        m_states.TryGetValue(stateID, out state);
        return state;
    }

    public IFSMState GetCurFSMState() {
        return m_curState;
    }

    private void init() {
    }

    public void RegistFSMState(IFSMState stateObj) {
        if(m_states.ContainsKey(stateObj.StateID)) {
            DebugUtil.LogError("RegistState repeat state!");
        } else {
            m_states.Add(stateObj.StateID, stateObj);
        }
    }

    public void StartStateMachine() {
        StopMachine();
        isFSMRunning = true;
        m_isPause = false;
        CurrentState = 0;
        StartCoroutine(StateMachine());
    }

    public void StopMachine() {
        StopAllCoroutines();
        isFSMRunning = false;
        m_curState = null;
        m_isPause = false;
        preStateID = -1;
    }

    IEnumerator StateMachine() {
        while(true) {
            debug_obj.PuppetLog("StateMachine--------------");
            if(!isFSMRunning) {
                yield return null;
            } else {
                if(m_curState != null) {
                    debug_isStateChanged = false;
                    debug_obj.PuppetLog("State Update. state:[{0}]", m_curState.Name);
                    //将会等待状态逻辑完成。
                    yield return StartCoroutine(m_curState.updateState());
                } else {
                    debug_obj.PuppetLogError("[FSM] state is null.preStateID:[{0}]", preStateID);
                    yield return null;
                }
            }
        }
    }

    public void Pause() {
        isFSMRunning = false;
    }

    public void Resume() {
        isFSMRunning = true;
    }

}
}
